<?php
/**
 * Created by PhpStorm.
 * User: wangsentao
 * Date: 2018/1/30
 * Time: 上午10:36
 */

namespace app\common\ShaoHuoPay\Gateways;

use app\common\ShaoHuoPay\Contracts\GatewayApplicationInterface;
use app\common\ShaoHuoPay\Contracts\GatewayInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use app\common\ShaoHuoPay\Exceptions\GatewayException;
use app\common\ShaoHuoPay\Exceptions\InvalidSignException;
use app\common\ShaoHuoPay\Gateways\Wechat\WxTools;
use app\common\ShaoHuoPay\tools\Str;
use app\common\ShaoHuoPay\tools\ShCollection;

class Wechat implements GatewayApplicationInterface
{
    /**
     * Config.
     *
     * @var Config
     */
    protected $config;

    /**
     * Wechat payload.
     *
     * @var array
     */
    protected $payload;

    /**
     * Wechat gateway.
     *
     * @var string
     */
    protected $gateway;

    /**
     * 初始
     * Wechat constructor.
     * @param $config
     */
    public function __construct( $config)
    {
        $this->config = $config;
        $this->gateway = WxTools::baseUri($this->config->get('mode', 'normal'));
        $this->payload = [
            'appid'            => $this->config->get('app_id', ''),
            'mch_id'           => $this->config->get('mch_id', ''),
            'nonce_str'        => Str::random(),
            'notify_url'       => $this->config->get('notify_url', ''),
            'sign'             => '',
            'trade_type'       => '',
            'spbill_create_ip' => Request::createFromGlobals()->getClientIp(),
        ];
    }

    /**
     * Pay an order.
     *
     * @author yansongda <me@yansongda.cn>
     *
     * @param string $gateway
     * @param array  $params
     *
     * @return Response|ShCollection
     */
    public function pay($gateway, $params = [])
    {

        $this->payload = array_merge($this->payload, $params);

        $gateway = get_class($this).'\\'.Str::studly($gateway).'Gateway';

        if (class_exists($gateway)) {
            return $this->makePay($gateway);
        }

        throw new GatewayException("Pay Gateway [{$gateway}] Not Exists", 1);
    }

    /**
     * Verify data.
     *
     * @author yansongda <me@yansongda.cn>
     *
     * @return ShCollection
     */
    public function verify()
    {
        $request = Request::createFromGlobals();

        $data = WxTools::fromXml($request->getContent());

        /*$xml = file_get_contents("php://input");
        $ardata = simplexml_load_string($xml);*/

        //WLog('wx_back_param.txt',  json_encode($data));

        if (WxTools::generateSign($data, $this->config->get('key')) === $data['sign']) {
            return new ShCollection($data);
        }

        throw new InvalidSignException('Wechat Sign Verify FAILED', 3, json_encode($data));
    }

    public function object_array($array)
    {
        if(is_object($array))
        {
            $array = (array)$array;
        }
        if(is_array($array))
        {
            foreach($array as $key=>$value)
            {
                $array[$key] = $this->object_array($value);
            }
        }
        return $array;
    }

    /**
     * Query an order.
     *
     * @author yansongda <me@yansongda.cn>
     *
     * @param string|array $order
     *
     * @return ShCollection
     */
    public function find($order)
    {
        $this->payload = WxTools::filterPayload($this->payload, $order, $this->config);

        return WxTools::requestApi('pay/orderquery', $this->payload, $this->config->get('key'));
    }

    /**
     * 退款
     * @param $order
     * @return ShCollection|mixed
     * @throws GatewayException
     * @throws InvalidSignException
     */
    public function refund($order)
    {
        $this->payload = WxTools::filterPayload($this->payload, $order, $this->config);

        return WxTools::requestApi(
            'secapi/pay/refund',
            $this->payload,
            $this->config->get('key'),
            $this->config->get('cert_client'),
            $this->config->get('cert_key')
        );
    }

    /**
     * 取消订单 微信没有提供 取消接口
     * @param $order
     * @return ShCollection
     * @throws GatewayException
     */
    public function cancel($order)
    {
        throw new GatewayException('Wechat Do Not Have Cancel API! Plase use Close API!', 3);
    }

    /**
     * 关闭订单
     * @param $order
     * @return ShCollection
     * @throws GatewayException
     * @throws InvalidSignException
     */
    public function close($order)
    {
        unset($this->payload['spbill_create_ip']);

        $this->payload = WxTools::filterPayload($this->payload, $order, $this->config);

        return WxTools::requestApi('pay/closeorder', $this->payload, $this->config->get('key'));
    }

    /**
     * 返回微信服务器成功信息
     * @return mixed|static
     * @throws \App\common\ShaoHuoPay\Exceptions\InvalidArgumentException
     */
    public function success()
    {
        return Response::create(
            WxTools::toXml(['return_code' => 'SUCCESS']),
            200,
            ['Content-Type' => 'application/xml']
        );
    }

    /**
     * @param $gateway
     * @return mixed
     * @throws GatewayException
     */
    protected function makePay($gateway)
    {
        $app = new $gateway($this->config);
        if ($app instanceof GatewayInterface) {

            return $app->pay($this->gateway, $this->payload);
        }

        throw new GatewayException("Pay Gateway [{$gateway}] Must Be An Instance Of GatewayInterface", 2);
    }

    /**
     * @param $method
     * @param $params
     * @return ShCollection|Response
     * @throws GatewayException
     */
    public function __call($method, $params)
    {
        return self::pay($method, ...$params);
    }
}